package com.laiketui.app.services.dubbo.auction;

import com.laiketui.app.api.auction.AuctionService;
import com.laiketui.common.api.PublicOrderService;
import com.laiketui.common.api.PubliceService;
import com.laiketui.common.api.plugin.PubliceAuctionService;
import com.laiketui.common.mapper.*;
import com.laiketui.common.utils.tool.cache.RedisDataTool;
import com.laiketui.common.utils.tool.str.StringUtils;
import com.laiketui.core.cache.RedisUtil;
import com.laiketui.core.exception.LaiKeAPIException;
import com.laiketui.core.lktconst.GloabConst;
import com.laiketui.core.utils.tool.DateUtil;
import com.laiketui.domain.lktconst.DictionaryConst;
import com.laiketui.domain.lktconst.ErrorCode;
import com.laiketui.domain.log.RecordModel;
import com.laiketui.domain.mch.MchModel;
import com.laiketui.domain.plugin.auction.AuctionPromiseModel;
import com.laiketui.domain.plugin.auction.AuctionRecordModel;
import com.laiketui.domain.plugin.jp.AuctionConfigModel;
import com.laiketui.domain.product.AuctionProductModel;
import com.laiketui.domain.user.User;
import com.laiketui.domain.vo.MainVo;
import com.laiketui.root.common.BuilderIDTool;
import com.laiketui.root.license.Md5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 竞拍实现
 *
 * @author Trick
 * @date 2021/4/22 10:01
 */
@Service
public class AuctionServiceImpl implements AuctionService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private PubliceAuctionService publiceAuctionService;

    @Autowired
    private AuctionProductModelMapper auctionProductModelMapper;

    @Autowired
    private AuctionRecordModelMapper auctionRecordModelMapper;

    @Autowired
    private AuctionPromiseModelMapper auctionPromiseModelMapper;

    @Autowired
    private AuctionConfigModelMapper auctionConfigModelMapper;

    @Autowired
    private RecordModelMapper recordModelMapper;

    @Autowired
    private UserBaseMapper userBaseMapper;

    @Autowired
    private PublicOrderService publicOrderService;

    @Autowired
    private PubliceService publiceService;

    @Autowired
    private MchModelMapper mchModelMapper;

    @Override
    public Map<String, Object> index(MainVo vo, String type) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            if (type == null) {
                type = "";
            }
            User user = RedisDataTool.getRedisUserCache(vo.getAccessId(), redisUtil);
            List<Map<String, Object>> goodsList;
            switch (type) {
                case "ready":
                    goodsList = publiceAuctionService.indexReady(vo.getStoreId(), vo.getPageNo(), vo.getPageSize());
                    break;
                case "running":
                    goodsList = publiceAuctionService.indexRunning(vo.getStoreId(), user, vo.getPageNo(), vo.getPageSize());
                    break;
                case "my":
                    goodsList = publiceAuctionService.indexMy(vo.getStoreId(), user, vo.getPageNo(), vo.getPageSize());
                    resultMap.put("res", goodsList);
                    break;
                default:
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_CSCW, "参数错误");
            }
            resultMap.put("is_user", user == null ? 0 : 1);
            resultMap.put("list", goodsList);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("获取竞拍列表 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "index");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> auctionGoodsDetail(MainVo vo, int id, String isfx) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            User user = RedisDataTool.getRedisUserCache(vo.getAccessId(), redisUtil);
            //获取竞拍信息
            AuctionProductModel auctionProductModel = new AuctionProductModel();
            auctionProductModel.setStore_id(vo.getStoreId());
            auctionProductModel.setId(id);
            auctionProductModel = auctionProductModelMapper.selectOne(auctionProductModel);
            if (auctionProductModel == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_JPSPBCZ, "竞拍商品不存在");
            }
            //获取店铺基本信息
            MchModel mchModel = mchModelMapper.selectByPrimaryKey(auctionProductModel.getMch_id());
            Map<String, Object> mchInfo = new HashMap<>(16);
            if (mchModel != null) {
                //获取店铺统计信息
                mchInfo = publiceService.commodityInformation(vo.getStoreId(), auctionProductModel.getMch_id());
                mchInfo.put("shop_id", mchModel.getId());
                mchInfo.put("shop_logo", publiceService.getImgPath(mchModel.getLogo(), vo.getStoreId()));
                mchInfo.put("shop_name", mchModel.getName());
            }
            //获取出价数量
            AuctionRecordModel auctionRecordModel = new AuctionRecordModel();
            auctionRecordModel.setStore_id(vo.getStoreId());
            auctionRecordModel.setAuction_id(auctionProductModel.getId());
            int bidNum = auctionRecordModelMapper.selectCount(auctionRecordModel);

            resultMap.putAll(publiceAuctionService.getAuctionDetail(id, user, "true".equals(isfx)));
            resultMap.put("is_user", user == null ? 0 : 1);
            resultMap.put("shop_list", mchInfo);
            resultMap.put("bid_num", bidNum);
            //最终成交人
            if (!StringUtils.isEmpty(auctionProductModel.getUser_id())) {
                resultMap.put("host_user", auctionProductModel.getUser_id());
            }
            resultMap.put("payment", publicOrderService.getPaymentConfig(vo.getStoreId()));
            resultMap.put("res_bid", publiceAuctionService.getAuctionRecordInfo(auctionProductModel.getStore_id(), auctionProductModel.getId(), 0, 3));
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("未开始和正在竞拍 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "auctionDetail");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> timeRequest(MainVo vo, int id) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            //获取竞拍活动信息
            AuctionProductModel auctionProductModel = auctionProductModelMapper.selectByPrimaryKey(id);
            //获取出价数量
            AuctionRecordModel auctionRecordModel = new AuctionRecordModel();
            auctionRecordModel.setStore_id(vo.getStoreId());
            auctionRecordModel.setAuction_id(auctionProductModel.getId());
            int bidNum = auctionRecordModelMapper.selectCount(auctionRecordModel);

            resultMap.put("res_bid", publiceAuctionService.getAuctionRecordInfo(auctionProductModel.getStore_id(), auctionProductModel.getId(), 0, 3));
            resultMap.put("max_price", auctionProductModel.getCurrent_price());
            resultMap.put("pepole", auctionProductModel.getPepole());
            resultMap.put("bid_num", bidNum);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("定时获取竞拍页面热数据 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "timeRequest");
        }
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> goPay(MainVo vo, int id, String password, String payType, Integer addressId) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            User user = RedisDataTool.getRedisUserCache(vo.getAccessId(), redisUtil, true);
            //是否线上支付标识
            boolean isOnlinePay = false;
            //获取竞拍商品信息
            AuctionProductModel auctionProductModel = auctionProductModelMapper.selectByPrimaryKey(id);
            if (auctionProductModel == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPBCZ, "商品不存在");
            }
            //保存押金
            AuctionPromiseModel auctionPromiseSave = new AuctionPromiseModel();
            //生成竞拍押金订单
            String orderno = DictionaryConst.OrdersType.ORDERS_HEADER_AC + BuilderIDTool.getNext(BuilderIDTool.Type.NUMBER, 18);
            if (DictionaryConst.OrderPayType.ORDERPAYTYPE_WALLET_PAY.equals(payType)) {
                //刷新用户缓存
                user = userBaseMapper.selectByPrimaryKey(user.getId());
                RedisDataTool.refreshRedisUserCache(vo.getAccessId(), user, redisUtil);
                if (StringUtils.isEmpty(user.getPassword())) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WSZMM, "未设置密码");
                } else if (!user.getPassword().equals(Md5Util.MD5endoce(password))) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_MMBZQ, "密码不正确");
                }
                //判断余额是否充足
                if (user.getMoney().compareTo(new BigDecimal(auctionProductModel.getPromise() + "")) < 0) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_YEBZ, "余额不足");
                } else {
                    int row = userBaseMapper.rechargeUserPrice(user.getId(), auctionProductModel.getPromise().negate());
                    if (row < 1) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                    }
                }
                //记录此次竞拍
                RecordModel recordModel = new RecordModel();
                recordModel.setStore_id(vo.getStoreId());
                recordModel.setUser_id(user.getUser_id());
                recordModel.setMoney(auctionProductModel.getPromise());
                recordModel.setOldmoney(user.getMoney());
                recordModel.setEvent("交竞拍押金");
                recordModel.setType(RecordModel.RecordType.PAY_AUCTION_DEPOSIT);
                recordModel.setAdd_date(new Date());
                int row = recordModelMapper.insertSelective(recordModel);
                if (row < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                //押金记录
                auctionPromiseSave.setIs_pay(1);
                //竞拍人数+1
                row = auctionProductModelMapper.addAuctionNumById(vo.getStoreId(), auctionProductModel.getId(), 1);
                if (row < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
                }
                resultMap.put("status", 2);
            } else {
                //其他线上支付  aliPay-支付宝支付 app_wechat-app微信支付 jsapi_wechat-微信内网页支付   mini_wechat-小程序微信支付
                auctionPromiseSave.setAllow_back(0);
                isOnlinePay = true;
            }
            auctionPromiseSave.setStore_id(vo.getStoreId());
            auctionPromiseSave.setUser_id(user.getUser_id());
            auctionPromiseSave.setPromise(auctionProductModel.getPromise());
//            auctionPromiseSave.setA_id(auctionProductModel.getId());
            auctionPromiseSave.setTrade_no(orderno);
            auctionPromiseSave.setAddress_id(addressId);
            auctionPromiseSave.setSource(vo.getStoreType());
            auctionPromiseSave.setType(payType);
            auctionPromiseSave.setAdd_time(new Date());
            int row = auctionPromiseModelMapper.insertSelective(auctionPromiseSave);
            if (row < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
            }
            if (isOnlinePay) {
                resultMap.put("status", 1);
                resultMap.put("title", "竞拍押金");
                resultMap.put("sNo", orderno);
                resultMap.put("total", auctionProductModel.getPromise());
                resultMap.put("pay_type", DictionaryConst.OrdersType.ORDERS_HEADER_JP);
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("交押金/出价 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "goPay");
        }
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> bid(MainVo vo, int id, BigDecimal price) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            User user = RedisDataTool.getRedisUserCache(vo.getAccessId(), redisUtil, true);
            //获取获取活动商品信息
            AuctionProductModel auctionProductModel = new AuctionProductModel();
            auctionProductModel.setStore_id(vo.getStoreId());
            auctionProductModel.setId(id);
            auctionProductModel = auctionProductModelMapper.selectOne(auctionProductModel);
            if (auctionProductModel == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPBCZ, "商品不存在");
            }
            //获取用户最后一次出价时间
            String addTime = auctionRecordModelMapper.selectAuctionTime(vo.getStoreId(), id, user.getUser_id());
            if (!StringUtils.isEmpty(addTime)) {
                //判断是否可以出价
                Date addDate = DateUtil.dateFormateToDate(addTime, GloabConst.TimePattern.YMDHMS);
                if (addDate != null) {
                    long outTime = DateUtil.getTime() - addDate.getTime() / 1000;
                    if (outTime < auctionProductModel.getWait_time()) {
                        throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_BZZJDSJQSHZS, "不在涨价的时间请稍后再试");
                    }
                }
            }
            //判断所加价格是否大于开拍加
            if (auctionProductModel.getPrice().compareTo(price) > 0) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_TBJGBDDYKPJ, "投标价格不得低于开盘价");
            }
            //判断出价金额是否大于最高价
            BigDecimal maxPrice = auctionRecordModelMapper.selectMaxPrice(vo.getStoreId(), auctionProductModel.getId());
            if (maxPrice != null) {
                //最新报价+加价幅度=加价门槛
                if (maxPrice.add(auctionProductModel.getAdd_price()).compareTo(price) > 0) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_TBJGBDDYZXBJ, "投标价格不得低于最新报价");
                }
            }
            AuctionRecordModel auctionRecordSave = new AuctionRecordModel();
            auctionRecordSave.setStore_id(vo.getStoreId());
            auctionRecordSave.setUser_id(user.getUser_id());
            auctionRecordSave.setAuction_id(auctionProductModel.getId());
            auctionRecordSave.setPrice(price);
            auctionRecordSave.setAdd_time(new Date());
            int row = auctionRecordModelMapper.insertSelective(auctionRecordSave);
            if (row < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
            }
            //更新竞拍价
            row = auctionProductModelMapper.updateAuctionPrice(price, vo.getStoreId(), auctionProductModel.getId());
            if (row < 1) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_ZFSB, "支付失败");
            }

            resultMap.put("suc", 1);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("出价 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "bid");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> rule(MainVo vo) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            String rule = "";
            AuctionConfigModel auctionConfigModel = new AuctionConfigModel();
            auctionConfigModel.setStore_id(vo.getStoreId());
            auctionConfigModel = auctionConfigModelMapper.selectOne(auctionConfigModel);
            if (auctionConfigModel != null) {
                rule = auctionConfigModel.getContent();
            }
            resultMap.put("my_rule", rule);
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("竞拍规则 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "rule");
        }
        return resultMap;
    }

    @Override
    public Map<String, Object> record(MainVo vo, int id) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            resultMap.put("res", publiceAuctionService.getAuctionRecordInfo(vo.getStoreId(), id, vo.getPageNo(), vo.getPageSize()));
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("出价记录 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "record");
        }
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> startAution(MainVo vo, int id) throws LaiKeAPIException {
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            //获取竞拍商品信息
            AuctionProductModel auctionProductModel = new AuctionProductModel();
            auctionProductModel.setStore_id(vo.getStoreId());
            auctionProductModel.setId(id);
            auctionProductModel = auctionProductModelMapper.selectOne(auctionProductModel);
            if (auctionProductModel == null) {
                throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_SPBCZ, "商品不存在");
            }
            if (auctionProductModel.getStatus() == AuctionProductModel.Status.NOT_START) {
                int row = auctionProductModelMapper.startAuction(vo.getStoreId(), id, new Date());
                if (row < 1) {
                    throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_CSCW, "参数错误");
                }
            }
        } catch (LaiKeAPIException l) {
            throw l;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("开始竞拍商品 异常" + e.getMessage());
            throw new LaiKeAPIException(ErrorCode.BizErrorCode.ERROR_CODE_WLYC, "网络异常", "startAution");
        }
        return resultMap;
    }
}

